package com.eipv.multidatasource.component.task;

import com.alibaba.fastjson.JSONObject;
import com.eipv.multidatasource.component.cache.QueueCache;
import com.eipv.multidatasource.component.cache.TableCache;
import com.eipv.multidatasource.condition.TableCondition;
import com.eipv.multidatasource.controller.WebSocketServerController;
import com.eipv.multidatasource.entity.Column;
import com.eipv.multidatasource.entity.SingleMonitor;
import com.eipv.multidatasource.entity.Table;
import com.eipv.multidatasource.entity.TotalMonitor;
import com.eipv.multidatasource.mapper.mysql.MysqlTableMapper;
import com.eipv.multidatasource.mapper.oracle.OracleTableMapper;
import com.eipv.multidatasource.util.SpringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;

public class ReadAndWriteFileTask implements Runnable {
    private String tableName;

    private int pageNum;

    private int pageSize;

    private AtomicLong total;

    private long start;


    public ReadAndWriteFileTask(String tableName, int pageNum, int pageSize, AtomicLong total, long start) {
        this.tableName = tableName;
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.total = total;
        this.start = start;
    }

    @Override
    public void run() {
        TotalMonitor totalMonitor = new TotalMonitor();
        SingleMonitor singleMonitor = new SingleMonitor();
        singleMonitor.setTableName(this.tableName);


        Table table = TableCache.TABLE_HANDLED.get(this.tableName);

        TableCache.TABLES_OF_PROCESSING.add(table);

        long localStart = System.currentTimeMillis();

        try {
            OracleTableMapper oracleTableMapper = SpringUtils.getBean(OracleTableMapper.class);

            TableCondition condition = new TableCondition();
            condition.setTableName(this.tableName);
            condition.setStart((this.pageNum - 1) * this.pageSize + 1);
            condition.setEnd(this.pageNum * this.pageSize);
            List<LinkedHashMap> list = oracleTableMapper.selectDataList(condition);
            StringBuilder sb = new StringBuilder();

            List<Column> columns = TableCache.COLUMNS.get(tableName);
            for (Column c : columns) {
                sb.append(c.getColumnName()).append(";");
            }
            sb = sb.replace(sb.lastIndexOf(";"), sb.length(), "\n");

            for (LinkedHashMap c : list) {
                for (Column column : columns) {
                    if (c.containsKey(column.getColumnName())) {
                        Object value = c.get(column.getColumnName());
                        if ("DATE".equals(column.getDataType())) {
                            //去掉.及后面的数字
                            if (value.toString().contains(".")) {
                                value = value.toString().substring(0, value.toString().indexOf("."));
                            }
                        }
                        sb.append(value).append(";");
                    } else {
                        sb.append(";");
                    }
                }
                sb = sb.replace(sb.lastIndexOf(";"), sb.length(), "\n");
            }

            File file = new File("/oracle/" + tableName + "_" + pageNum + "-" + list.size() + ".txt");
            OutputStream os = new FileOutputStream(file, true);
            os.write(sb.toString().getBytes());
            os.flush();
            os.close();
            singleMonitor.setFileName(file.getAbsolutePath());

            // 缓存
            QueueCache.FILE_QUEUE.put(file);
            TableCache.rowsOfRead.addAndGet(list.size());
            table.updateHandled((long) list.size());
            table.updateReadRows((long) list.size());
            table.updateTransferred(file.length());
            table.updateTransferTime(System.currentTimeMillis() - localStart);


            totalMonitor.setTables(TableCache.TABLES_OF_NEED_MIGRATE.size());
            totalMonitor.setCompleted(TableCache.TABLES_OF_COMPLETED.size());
            totalMonitor.setProcessing(TableCache.TABLES_OF_PROCESSING.size());
            totalMonitor.setFailed(TableCache.TABLES_OF_FAILED.size());
            totalMonitor.setVolume(TableCache.volume.addAndGet(file.length()));
            totalMonitor.setRowsOfRead(table.getRowsOfRead());
            long waste = System.currentTimeMillis() - start;
            totalMonitor.setTransferTime(new BigDecimal(waste).divide(new BigDecimal(1000), 3, BigDecimal.ROUND_CEILING));

            BigDecimal speedOfSize = new BigDecimal(TableCache.volume.get()).divide(new BigDecimal(waste).divide(new BigDecimal(1000)), 3, BigDecimal.ROUND_CEILING);
            totalMonitor.setSpeedOfSize(speedOfSize);

            BigDecimal speedOfRows = new BigDecimal((TableCache.rowsOfRead.get() + TableCache.rowsOfWrite.get()) / 2).divide(new BigDecimal(waste).divide(new BigDecimal(1000)), 0, BigDecimal.ROUND_CEILING);
            totalMonitor.setSpeedOfRows(speedOfRows);


            singleMonitor.setRowsOfRead(table.getRowsOfRead());
            singleMonitor.setRowsOfWrite(table.getRowsOfWrite());
            singleMonitor.setTransferred(table.getTransferred());
            singleMonitor.setTransferTime(table.getTransferTime());

        } catch (Exception e) {
            e.printStackTrace();
            singleMonitor.setException(e.getLocalizedMessage());
            singleMonitor.setStatus(SingleMonitor.FAILED);

            TableCache.TABLES_OF_PROCESSING.remove(table);
            TableCache.TABLES_OF_FAILED.add(table);
        } finally {
            TableCache.TABLE_HANDLED.put(this.tableName, table);

            try {
                QueueCache.MONITOR_QUEUE.put(totalMonitor);
                QueueCache.MONITOR_QUEUE.put(singleMonitor);
            } catch (InterruptedException e) {
                System.out.println("监控存入队列报错");
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws ParseException {
        String date = "2016-06-30 13:04:41.0";
        Date d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S").parse(date);
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d));
    }
}
